package cn.tedu.jdbc;

import cn.tedu.jdbc.utils.DbUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

/**
 * 实现用户登录功能
 * 这个程序在实现了基本的登录功能的同时，演示了SQL注入的现象
 * 导致SQL注入现象的根本原因是什么？
 * 1.用户提供的信息中含有SQL语句的关键字了
 * 2.这些用户提供的信息中的关键字参与了SQL语句的编译
 *
 * SQL注入是一种安全隐患，黑客通常使用SQL注入来攻击你的系统
 * 怎么避免SQL注入现象呢？
 *
 * java.sql.Statement 是存在SQL注入现象的，因为它的原理是：相拼接SQL语句字符串，然后在进行编译，所以他必然存在SQL注入的问题。
 * 为了避免 SQL注入的发生，JDBC API 中为Statement接口提供了一个子接口：java.sql.PreparedStatement，被称为与变异的数据库操作对象。
 * java.sql.PreparedStatement可以解决SQL注入问题。
 *
 * 具体怎么解决？
 * PreparedStatement可以对SQL语句进行预先编译，然后给编译好的SQL语句占位符传值，通过这种方式来解决SQL注入问题
 * 最本质的解决方法是：用户虽然提供了SQL语句关键字，但是这些关键字不再参与SQL语句的编译了。因此解决了SQL注入的问题。
 *
 */
public class JDBCTest10 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //初始化登录界面
        System.out.println("欢迎使用用户管理系统，请登录！");
        System.out.println("用户名:");
//        String loginName = scanner.next();
        String loginName = scanner.nextLine();//读取一行
        System.out.println("密码:");
//        String loginpwd = scanner.next();
        String loginpwd = scanner.nextLine();

        //连接数据库，验证用户名和密码是否正确。
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        boolean loginSuccess = false;
        String realname = null;

        try {
            conn = DbUtils.getConnection();
            stmt = conn.createStatement();
            String sql = "select * from t_user where name = '" + loginName + "' and password = '" + loginpwd + "'";
            //导致SQL注入现象的最根本的原因是什么？
            //先进行了SQL语句的字符串拼接，
            //然后再进行SQL语句的编译
            rs = stmt.executeQuery(sql);
            //处理结果集（结果集中有数据，表示登陆成功，反之表示登录失败）
            if (rs.next()){
                //登陆成功
                loginSuccess  = true;
                //获取真实名字
                realname = rs.getString("realname");

            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            DbUtils.close(conn, stmt, rs);
        }
        System.out.println(loginSuccess ? "登陆成功，欢迎" + realname : "登录失败，您的用户名或密码有误！");
    }
}
